package cn.tedu.tmall.passport.service.impl;

import cn.tedu.tmall.common.enumerator.ServiceCode;
import cn.tedu.tmall.common.ex.ServiceException;
import cn.tedu.tmall.common.pojo.authentication.CurrentPrincipal;
import cn.tedu.tmall.common.pojo.po.UserStatePO;
import cn.tedu.tmall.passport.dao.cache.IUserCacheRepository;
import cn.tedu.tmall.passport.dao.persist.repository.IUserRepository;
import cn.tedu.tmall.passport.pojo.param.UserLoginInfoParam;
import cn.tedu.tmall.passport.pojo.vo.UserLoginInfoVO;
import cn.tedu.tmall.passport.pojo.vo.UserLoginResultVO;
import cn.tedu.tmall.passport.service.IUserService;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class UserServiceImpl implements IUserService {

    @Value("${tmall.jwt.secret-key}")
    private String secretKey;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private IUserRepository userRepository;

    @Autowired
    private IUserCacheRepository userCacheRepository;

    @Override
    public UserLoginResultVO login(UserLoginInfoParam userLoginInfoParam,
                                   String remoteAddr,String userAgent) {
        String username = userLoginInfoParam.getUsername();
        UserLoginInfoVO queryResult = userRepository.getLoginInfoByUsername(username);
        if (queryResult == null) {
            String message = "登录失败,用户名或密码错误! [1]";
            throw new ServiceException(ServiceCode.ERROR_UNAUTHORIZED,message);
        }

        if (queryResult.getEnable() == 0){
            String message = "登录失败,账号被禁用!";
            throw new ServiceException(ServiceCode.ERROR_UNAUTHORIZED_DISABLED,message);
        }

        String password = userLoginInfoParam.getPassword();
        if (!passwordEncoder.matches(password, queryResult.getPassword())){
            String message = "登录失败,用户名或者密码错误! [2]";
            throw new ServiceException(ServiceCode.ERROR_UNAUTHORIZED,message);
        }

        // TODO 向登录日志表(account_login_log)中插入数据
        // TODO 登录用户名(account_user)中当前用户的相关信息（登录次数、最后登录IP、最后登录时间）

//        // 创建当事人信息
//        CurrentPrincipal principal = new CurrentPrincipal();
//        principal.setId(queryResult.getId());
//        principal.setUsername(queryResult.getUsername());
//
//        // 准备权限列表
//        ArrayList<SimpleGrantedAuthority> authorities = new ArrayList<>();
//        List<String> permissions = queryResult.getPermissions();
//        for (String permission : permissions) {
//            SimpleGrantedAuthority authority = new SimpleGrantedAuthority(permission);
//            authorities.add(authority);
//        }
//
//        // 向Security中存入有效的Authentication
//        //String principal = queryResult.getUsername();
//        Authentication authentication = new UsernamePasswordAuthenticationToken(
//                principal,null,authorities);
//        SecurityContext securityContext = SecurityContextHolder.getContext();
//        securityContext.setAuthentication(authentication);

        List<String> permissions = queryResult.getPermissions();
        String authoritiesJsonString = JSON.toJSONString(permissions);

        UserStatePO userStatePO = new UserStatePO();
        userStatePO.setAuthoritiesJsonString(authoritiesJsonString);
        userStatePO.setEnable(1);

        userCacheRepository.saveUserState(queryResult.getId(), userStatePO);

        Map<String, Object> claims = new HashMap<>();
        claims.put("id", queryResult.getId());
        claims.put("username", queryResult.getUsername());
        claims.put("agent",userAgent);
        claims.put("address",remoteAddr);
        String jwt = Jwts.builder()
                // Header
                .setHeaderParam("alg", "HS256")
                .setHeaderParam("typ", "JWT")
                // Payload
                .setClaims(claims)
                //.setExpiration(new Date(System.currentTimeMillis() + 60 * 1000)) //设置有效期,确定过期时间
                // Verify Signature
                .signWith(SignatureAlgorithm.HS256, secretKey)
                // 完成
                .compact();

        UserLoginResultVO loginResult = new UserLoginResultVO();
        BeanUtils.copyProperties(queryResult,loginResult);
        loginResult.setToken(jwt);
        return loginResult;
    }

    @Override
    public void logout(CurrentPrincipal currentPrincipal) {
        Long userId = currentPrincipal.getId();
        userCacheRepository.deleteUserState(userId);
    }
}
